package com.xique.park.service.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xique.common.core.domain.R;
import com.xique.common.core.web.domain.PageResult;
import com.xique.park.bean.domain.ParkStatisticsIncome;
import com.xique.park.bean.vo.web.statistics.ParkStatisticsIncomeVo;
import com.xique.park.mapper.ParkStatisticsIncomeMapper;
import com.xique.park.service.service.IParkStatisticsIncomeService;
import com.xique.park.service.service.IPayOrderService;
import com.xique.system.api.RemoteSystemProjectService;
import com.xique.system.api.dto.SystemProjectDTO;
import com.xique.system.api.request.RemoteSystemProjectAllListRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 收入统计报表服务接口实现
 *
 * @author WLD
 */
@RequiredArgsConstructor
@Service
public class ParkStatisticsIncomeServiceImpl extends ServiceImpl<ParkStatisticsIncomeMapper, ParkStatisticsIncome> implements IParkStatisticsIncomeService {

    private final RemoteSystemProjectService remoteSystemProjectService;

    private final IPayOrderService payOrderService;

    private final ParkStatisticsIncomeMapper parkStatisticsIncomeMapper;

    private static final String TIME_ZERO = "00:00:00";

    @Override
    public void initParkStatisticsIncome(Long parkId) {
        if (parkId == null) {
            // 获取所有项目列表
            R<List<SystemProjectDTO>> systemProjectListResult = remoteSystemProjectService.getProjectList(new RemoteSystemProjectAllListRequest());
            List<SystemProjectDTO> systemProjectList = systemProjectListResult.getData();
            // 初始化所有项目
            systemProjectList.forEach(systemProjectDTO -> {
                Long projectId = systemProjectDTO.getId();
                initProjectStatisticsIncome(projectId);
            });
        } else {
            // 初始化当前项目
            initProjectStatisticsIncome(parkId);
        }
    }

    private void initProjectStatisticsIncome(Long parkId) {
        // 根据项目ID统计收入信息
        List<ParkStatisticsIncome> parkStatisticsIncomeList = payOrderService.selectStatisticsIncomeByDay(parkId);
        if (CollUtil.isNotEmpty(parkStatisticsIncomeList)) {
            // 删除之前的记录
            deleteByParkId(parkId);
            parkStatisticsIncomeList.forEach(parkStatisticsIncome -> {
                parkStatisticsIncome.setParkId(parkId);
                parkStatisticsIncome.setCreateTime(LocalDateTime.now());
            });
            // 新增记录
            saveBatch(parkStatisticsIncomeList);
        }
    }

    private void deleteByParkId(Long parkId) {
        LambdaQueryWrapper<ParkStatisticsIncome> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ParkStatisticsIncome::getParkId, parkId);
        remove(queryWrapper);
    }

    @Override
    public void statisticsIncomeByDay(String day) {
        // 获取所有项目列表
        R<List<SystemProjectDTO>> systemProjectListResult = remoteSystemProjectService.getProjectList(new RemoteSystemProjectAllListRequest());
        List<SystemProjectDTO> systemProjectList = systemProjectListResult.getData();
        // 新增每个项目指定日期的收入统计
        systemProjectList.forEach(systemProjectDTO -> {
            Long parkId = systemProjectDTO.getId();
            if (parkId != null && day != null) {
                ParkStatisticsIncome parkStatisticsIncome = payOrderService.selectStatisticsIncomeByAppointDay(day, parkId);
                if (null == parkStatisticsIncome) {
                    parkStatisticsIncome = new ParkStatisticsIncome();
                }
                parkStatisticsIncome.setParkId(parkId);
                parkStatisticsIncome.setStatisticalTime(DateUtil.parseLocalDateTime(day + " " + TIME_ZERO));
                parkStatisticsIncome.setCreateTime(LocalDateTime.now());

                LambdaQueryWrapper<ParkStatisticsIncome> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(ParkStatisticsIncome::getParkId, parkId);
                queryWrapper.eq(ParkStatisticsIncome::getStatisticalTime, day);

                saveOrUpdate(parkStatisticsIncome, queryWrapper);
            }
        });
    }

    @Override
    public PageResult getParkStatisticsIncome(Long parkId, Integer type, String startTime, String endTime, Integer pageNum, Integer pageSize) {
        Page<ParkStatisticsIncomeVo> page = new Page<>();
        page.setCurrent(pageNum);
        page.setSize(pageSize);

        IPage<ParkStatisticsIncomeVo> iPage;

        switch (type) {
            // 按日
            case 1:
                iPage = parkStatisticsIncomeMapper.selectPageByDay(page, parkId, startTime, endTime);
                handlePageResult(iPage.getRecords());
                break;
            // 按月
            case 2:
                iPage = parkStatisticsIncomeMapper.selectPageByMonth(page, parkId, startTime, endTime);
                handlePageResult(iPage.getRecords());
                break;
            // 按年
            case 3:
                iPage = parkStatisticsIncomeMapper.selectPageByYear(page, parkId, startTime, endTime);
                handlePageResult(iPage.getRecords());
                break;
            default:
                throw new IllegalArgumentException("收入统计报表查询类型错误，请联系管理员");
        }

        return PageResult.builder()
                .pageNum(pageNum)
                .pageSize(pageSize)
                .totalPages(iPage.getPages())
                .totalSize(iPage.getTotal())
                .list(iPage.getRecords())
                .build();
    }

    private void handlePageResult(List<ParkStatisticsIncomeVo> parkStatisticsIncomeVoList) {
        if (CollUtil.isNotEmpty(parkStatisticsIncomeVoList)) {
            parkStatisticsIncomeVoList.forEach(parkStatisticsIncomeVo -> {
                // 月卡现金收入
                BigDecimal monthlyCardCash = parkStatisticsIncomeVo.getMonthlyCardCash();

                // 月卡电子支付
                BigDecimal monthlyCardElectronics = parkStatisticsIncomeVo.getMonthlyCardElectronics();

                // 月卡收入合计
                BigDecimal monthlyTotal = monthlyCardCash.add(monthlyCardElectronics);
                parkStatisticsIncomeVo.setMonthlyTotal(monthlyTotal);

                // 临停现金收入
                BigDecimal temporaryCash = parkStatisticsIncomeVo.getTemporaryCash();

                // 临停电子支付
                BigDecimal temporaryElectronics = parkStatisticsIncomeVo.getTemporaryElectronics();

                // 临停etc收入
                BigDecimal temporaryEtc = parkStatisticsIncomeVo.getTemporaryEtc();

                // 临停收入合计
                BigDecimal temporaryTotal = temporaryCash.add(temporaryElectronics).add(temporaryEtc);
                parkStatisticsIncomeVo.setTemporaryTotal(temporaryTotal);

                // 储值现金收入
                BigDecimal storedValueCash = parkStatisticsIncomeVo.getStoredValueCash();

                // 储值电子收入
                BigDecimal storedValueElectronics = parkStatisticsIncomeVo.getStoredValueElectronics();

                // 储值收入合计
                BigDecimal storedValueTotal = storedValueCash.add(storedValueElectronics);
                parkStatisticsIncomeVo.setStoredValueTotal(storedValueTotal);

                // 商家现金收入，商家收入合计
                parkStatisticsIncomeVo.setBusinessTotal(parkStatisticsIncomeVo.getBusinessCash());

                // 总收入
                BigDecimal total = monthlyTotal.add(temporaryTotal).add(storedValueTotal).add(parkStatisticsIncomeVo.getBusinessCash());
                parkStatisticsIncomeVo.setTotal(total);

                // 统计时间处理
                String statisticalTimeStr = parkStatisticsIncomeVo.getStatisticalTimeStr();
                if (StrUtil.isNotBlank(statisticalTimeStr) && statisticalTimeStr.contains(TIME_ZERO)) {
                    statisticalTimeStr = statisticalTimeStr.substring(0, statisticalTimeStr.lastIndexOf(TIME_ZERO));
                    parkStatisticsIncomeVo.setStatisticalTimeStr(statisticalTimeStr);
                }
            });
        }
    }

}
